package com.etalk.crm.serviceImpl;

import com.alibaba.fastjson.JSON;
import com.etalk.crm.client.InvokingService;
import com.etalk.crm.dao.PersonMapper;
import com.etalk.crm.dao.QuestionMapper;
import com.etalk.crm.dao.TestPaperMapper;
import com.etalk.crm.dao.TextBooksMapper;
import com.etalk.crm.pojo.PaperTrackRecord;
import com.etalk.crm.pojo.Person;
import com.etalk.crm.pojo.QuestionBanks;
import com.etalk.crm.pojo.QuestionItem;
import com.etalk.crm.pojo.TestPaper;
import com.etalk.crm.pojo.TestPaperQBankRelation;
import com.etalk.crm.pojo.TestPaperType;
import com.etalk.crm.service.QuestionService;
import com.etalk.crm.service.TestPaperService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.etalk.crm.utils.Constants.PAPER_STATE_FINISH;

/**
 * @author Terwer
 */
@Service
public class TestPaperServiceImpl implements TestPaperService {

    private static final Logger logger = LogManager.getLogger(MenuInfoServiceImpl.class);

    @Resource
    private TestPaperMapper testPaperMapper;

    @Resource
    private QuestionMapper questionMapper;

    @Resource
    private QuestionService questionService;

    @Resource
    private PersonMapper personMapper;

    @Resource
    private TextBooksMapper textBooksMapper;

    @Resource
    private InvokingService invokingService;

    @Override
    public PageInfo<TestPaper> getTestPaperList(Map<String, Object> paramMap, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        logger.info("getPaperListByPage入参为：" + JSON.toJSONString(paramMap));
        List<TestPaper> list = testPaperMapper.selectPaperListByPage(paramMap);
        //分页信息
        PageInfo<TestPaper> pageInfo = new PageInfo<>(list);
        long total = pageInfo.getTotal();
        int pages = pageInfo.getPages();
        if (pageNum > pages) {
            return new PageInfo<>();
        }
        pageNum = pageInfo.getPageNum();
        pageSize = pageInfo.getPageSize();
        logger.info("分页信息：total=" + total + "，pages=" + pages + "，pageNum=" + pageNum + "，pageSize=" + pageSize + "，搜索条件：paramMap=" + paramMap);
        return pageInfo;
    }

    @Override
    public PageInfo<TestPaper> getSendedPaperListList(Map<String, Object> paramMap, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        logger.info("getPaperListByPage入参为：" + JSON.toJSONString(paramMap));
        List<TestPaper> list = testPaperMapper.selectSendedPaperListByPage(paramMap);
        //分页信息
        PageInfo<TestPaper> pageInfo = new PageInfo<>(list);
        long total = pageInfo.getTotal();
        int pages = pageInfo.getPages();
        if (pageNum > pages) {
            return new PageInfo<>();
        }
        pageNum = pageInfo.getPageNum();
        pageSize = pageInfo.getPageSize();
        logger.info("分页信息：total=" + total + "，pages=" + pages + "，pageNum=" + pageNum + "，pageSize=" + pageSize + "，搜索条件：paramMap=" + paramMap);
        return pageInfo;
    }

    @Override
    public TestPaper getTestPaperByTestPaperId(Integer testPaperId) {
        //查询不包含正确答案的试卷信息
        TestPaper testPaper = this.selectByTestPaperIdAndScoreId(testPaperId, 0);
        return testPaper;
    }

    @Override
    public TestPaper getBasicInfoByTestPaperId(Integer testPaperId) {
        //试卷基本信息
        TestPaper testPaper = testPaperMapper.selectByTestPaperId(testPaperId);
        if (null == testPaper) {
            logger.error("查询试卷信息失败：试卷ID=" + testPaperId);
            return null;
        }
        return testPaper;
    }

    @Override
    public TestPaper selectBasicInfoByTestPaperIdAndScoreId(Integer testPaperId, Integer scoreId) {
        //试卷基本信息
        TestPaper testPaper = null;
        if (null == scoreId || scoreId == 0) {
            testPaper = testPaperMapper.selectByTestPaperId(testPaperId);
        } else {
            //有分数查询做过的试卷
            testPaper = testPaperMapper.selectPaperByScoreId(scoreId);
            logger.info("查询做过的试卷:testPaper=" + testPaper);
        }

        if (null == testPaper) {
            logger.error("查询试卷信息失败：试卷ID=" + testPaperId);
        }
        return testPaper;
    }

    @Override
    public TestPaper selectByTestPaperIdAndScoreId(Integer testPaperId, Integer scoreId) {
        //试卷基本信息
        TestPaper testPaper = selectBasicInfoByTestPaperIdAndScoreId(testPaperId, scoreId);

        // 题目信息
        List<QuestionItem> listQuestionItems = getQuestionList(testPaperId, scoreId);
        testPaper.setListQuestionItems(listQuestionItems);
        return testPaper;
    }

    /**
     * 获取试卷中题目列表
     *
     * @param testPaperId
     * @param scoreId
     * @return
     */
    private List<QuestionItem> getQuestionList(Integer testPaperId, Integer scoreId) {
        //题目信息
        //查询大题标题
        List<Map> questionTitleList = testPaperMapper.selectQuestionTitleList(testPaperId);
        //查询小题信息
        List<QuestionItem> listQuestionItems = new ArrayList<>();
        for (Map questionMap : questionTitleList) {
            String questionTitle = (String) questionMap.getOrDefault("title", "");
            Integer questionId = (Integer) questionMap.getOrDefault("id", 0);

            QuestionItem questionItem = new QuestionItem();
            questionItem.setQuestionTitle(questionTitle);
            //查询大题下面的所有子题目的信息
            List<QuestionBanks> listQuestionBanks = testPaperMapper.selectQuestionBanksList(testPaperId, questionId);

            List<QuestionBanks> detailedListQuestionBanks = new ArrayList<>(listQuestionBanks.size());
            //初始化子题目
            for (QuestionBanks questionBanks : listQuestionBanks) {
                //设置属性及子题目
                QuestionBanks detailedQuestionBanks = questionService.initQuestionBanks(questionBanks, scoreId);
                detailedListQuestionBanks.add(detailedQuestionBanks);
            }
            questionItem.setListQuestionBanks(detailedListQuestionBanks);
            listQuestionItems.add(questionItem);
        }
        return listQuestionItems;
    }

    @Override
    public List<TestPaperType> selectPaperTypeList() {
        return testPaperMapper.selectPaperTypeList();
    }

    @Transactional
    @Override
    public boolean saveTestPaper(TestPaper testPaper) {
        if (testPaper.getId() != null && testPaper.getId() > 0) {
            logger.info("开始修改试卷信息：入参=" + JSON.toJSONString(testPaper));
            int count = testPaperMapper.updateTestPaper(testPaper);
            if (count > 0) {
                // 添加教材关联,需要先删除
                testPaperMapper.deleteTextbokPaper(testPaper.getId());
                if (!CollectionUtils.isEmpty(testPaper.getTextbooksList())) {
                    testPaperMapper.batchSaveTextbookPaper(testPaper.getTextbooksList());
                }

                logger.info("试卷修改成功：testPaperId=" + testPaper.getId());
                return true;
            }
        } else {
            logger.info("开始生成试卷：入参=" + JSON.toJSONString(testPaper));
            int count = testPaperMapper.saveTestPaper(testPaper);
            if (count > 0) {
                logger.debug("试卷ID：" + testPaper.getId());

                // 添加教材关联
                List<Map> textbookListMap = testPaper.getTextbooksList();
                if (!CollectionUtils.isEmpty(textbookListMap)) {
                    for (Map item : textbookListMap) {
                        item.put("testPaperId", testPaper.getId());
                    }
                    testPaperMapper.batchSaveTextbookPaper(textbookListMap);
                }

                List<TestPaperQBankRelation> testPaperQBankRelationList = new ArrayList<>();
                for (QuestionItem questionItem : testPaper.getListQuestionItems()) {
                    //临时解决传空值问题，根本方案是改进vue前端删除逻辑
                    if (null == questionItem.getQuestionTitle()) {
                        continue;
                    }

                    //大题标题
                    QuestionBanks qbank = new QuestionBanks();
                    qbank.setParentid(-1);
                    qbank.setTitle(questionItem.getQuestionTitle());
                    qbank.setQtitle("");
                    qbank.setQgradeId(0);
                    qbank.setMistakeId(0);
                    qbank.setQtypeId(0);
                    questionMapper.saveQuestionBank(qbank);

                    TestPaperQBankRelation testPaperQBankRelation = new TestPaperQBankRelation();
                    testPaperQBankRelation.setTestPaperId(testPaper.getId());
                    testPaperQBankRelation.setQbankId(qbank.getId());
                    testPaperQBankRelation.setQbankParentid(0);
                    testPaperQBankRelation.setSort(1);
                    testPaperQBankRelationList.add(testPaperQBankRelation);

                    //小题
                    for (QuestionBanks questionBanks : questionItem.getListQuestionBanks()) {
                        testPaperQBankRelation = new TestPaperQBankRelation();
                        testPaperQBankRelation.setTestPaperId(testPaper.getId());
                        testPaperQBankRelation.setQbankId(questionBanks.getId());
                        testPaperQBankRelation.setQbankParentid(qbank.getId());
                        testPaperQBankRelation.setSort(questionBanks.getSort());
                        testPaperQBankRelationList.add(testPaperQBankRelation);
                    }
                }

                int result = testPaperMapper.batchSavePaperQBankRelation(testPaperQBankRelationList);
                if (result > 0) {
                    return true;
                }
            }
        }
        return false;
    }

    @Transactional
    @Override
    public boolean deleteTestPaper(Integer testPaperId) {
        //删除大题标题
        questionMapper.deleteQuestionTitleByTestPaperId(testPaperId);
        //删除试卷题目关联
        testPaperMapper.deleteQBankRelation(testPaperId);
        //删除试卷信息
        testPaperMapper.deleteTestPaperByTestPaperId(testPaperId);
        //删除分数关联
        testPaperMapper.deletePaperScore(testPaperId);
        //删除做题记录关联
        testPaperMapper.deleteInputAnswer(testPaperId);
        return true;
    }

    @Override
    public PageInfo<Person> getStudentList(String studentName, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        List<Person> list = personMapper.selectStudentListByPaperSend(studentName);
        // 分页信息
        PageInfo<Person> pageInfo = new PageInfo<Person>(list);
        long total = pageInfo.getTotal();
        int pages = pageInfo.getPages();
        pageNum = pageInfo.getPageNum();
        pageSize = pageInfo.getPageSize();
        logger.info("分页信息：total=" + total + "，pages=" + pages + "，pageNum=" + pageNum + "，pageSize=" + pageSize + "，搜索关键字：studentName=" + studentName);
        return pageInfo;
    }

    @Override
    public PageInfo<TestPaper> getPaperListByPersonId(Integer personId, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("personId", personId);
        List<TestPaper> list = testPaperMapper.selectPaperListByPage(paramMap);
        // 分页信息
        PageInfo<TestPaper> pageInfo = new PageInfo<>(list);
        long total = pageInfo.getTotal();
        int pages = pageInfo.getPages();
        pageNum = pageInfo.getPageNum();
        pageSize = pageInfo.getPageSize();
        logger.info("分页信息：total=" + total + "，pages=" + pages + "，pageNum=" + pageNum + "，pageSize=" + pageSize);
        return pageInfo;
    }

    @Override
    public boolean checkTestState(Integer paperId, Integer personId) {
        Integer state = testPaperMapper.checkTestState(paperId, personId);
        //最近一次的试卷未完成，不允许再次做题
        if (null != state && state < PAPER_STATE_FINISH) {
            return false;
        }
        return true;
    }

    @Transactional
    @Override
    public Integer sendPaperToStudent(Integer paperId, Integer personId) {
        Map paramMap = new HashMap();
        paramMap.put("paperId", paperId);
        paramMap.put("personId", personId);
        testPaperMapper.saveTestPaperScores(paramMap);
        Integer scoreId = (Integer) paramMap.getOrDefault("scoreId", 0);
        return scoreId;
    }

    @Transactional
    @Override
    public boolean changePaperState(Integer scoreId, Integer state) {
        //  修改试卷状态
        Integer result = testPaperMapper.changePaperState(scoreId, state);
        if (result > 0) {
            return true;
        }
        return false;
    }

    @Override
    public Map selectByStudentAndPage(Integer personId, String stateList, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        List stList = new ArrayList();
        if (null != stateList) {
            stList = Arrays.asList(stateList.split(","));
        }
        List<Map> list = testPaperMapper.selectByStudentAndPage(personId, stList);
        // 获取教材封面
        for (Map map : list) {
            Integer textbooksId = Integer.parseInt(String.valueOf(map.getOrDefault("textbooksId", "0")));
            String address = textBooksMapper.selectAddressByTextbooksId(textbooksId);
            String textbooksUrl = "http://hkmaterials.etalk365.com/" + address + "/1.png";
            map.put("textbooksUrl", textbooksUrl);
            Date submitTime = (Date) map.get("submitTime");
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            map.put("submitTime", sdf.format(submitTime));
        }

        //分页信息
        PageInfo<Map> pageInfo = new PageInfo<>(list);
        long total = pageInfo.getTotal();
        int pages = pageInfo.getPages();
        pageNum = pageInfo.getPageNum();
        pageSize = pageInfo.getPageSize();
        Map resultMap = new HashMap();
        resultMap.put("count", pageInfo.getSize());
        resultMap.put("list", list);
        logger.info("分页信息：total=" + total + "，pages=" + pages + "，pageNum=" + pageNum + "，pageSize=" + pageSize);
        return resultMap;
    }

    @Override
    public List<Map> getTestPaperQuestionInfo(Map paramMap) {
        return testPaperMapper.selectTestPaperQuestionInfo(paramMap);
    }

    @Override
    public Integer getTestPaperQuestionInfoCount(Map paramMap) {
        List<Map> list = testPaperMapper.selectTestPaperQuestionInfo(paramMap);
        if (!CollectionUtils.isEmpty(list)) {
            Map resultMap = list.get(0);
            return Math.toIntExact((long) resultMap.getOrDefault("count", 0));
        }
        return 0;
    }

    @Override
    public PageInfo<Map> getTestPaperQuestionInfoByPage(Map paramMap, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        List<Map> list = testPaperMapper.selectTestPaperQuestionInfo(paramMap);
        //分页信息
        PageInfo<Map> pageInfo = new PageInfo<>(list);
        long total = pageInfo.getTotal();
        int pages = pageInfo.getPages();
        if (pageNum > pages) {
            return new PageInfo<>();
        }
        pageNum = pageInfo.getPageNum();
        pageSize = pageInfo.getPageSize();
        logger.info("分页信息：total=" + total + "，pages=" + pages + "，pageNum=" + pageNum + "，pageSize=" + pageSize);
        return pageInfo;
    }

    @Override
    public boolean checkIsAuto(Integer scoreId) {
        int count = testPaperMapper.checkIsAuto(scoreId);
        // 包含11作文题，12阅读问答题，13翻译题的试卷不能自动批改
        if (count > 0) {
            return false;
        }
        return true;
    }

    @Transactional
    @Override
    public boolean batchSaveTestPaperScoresByTextbook(Integer paperId) {
        List<Integer> learningStudentList = testPaperMapper.selectLearingStudentList(paperId);
        logger.debug("发给试卷" + paperId + "的学生列表：" + JSON.toJSONString(learningStudentList));
        if (!CollectionUtils.isEmpty(learningStudentList)) {
            // 批量发送试卷
            List<Map> paramList = new ArrayList<>(learningStudentList.size());
            for (Integer personId : learningStudentList) {
                Map paramMap = new HashMap();
                paramMap.put("personId", personId);
                paramList.add(paramMap);
            }
            int count = testPaperMapper.batchSaveTestPaperScoresByTextbook(paperId, paramList);

            // 试卷发送成功，发送微信通知
            if (count > 0) {
                TestPaper paperInfo = getBasicInfoByTestPaperId(paperId);
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
                String sendDate = sdf.format(new Date());
                for (Integer personId : learningStudentList) {
                    invokingService.sendDoingPapersMessage(personId, paperInfo.getPaperName(), sendDate);
                }
                return true;
            }
        }
        return false;
    }

    @Transactional
    @Override
    public boolean updatePaperTrackStatus(Integer scoreId, Integer trackStatus) {
        int count = testPaperMapper.updatePaperTrackStatus(scoreId, trackStatus);
        if (count > 0) {
            return true;
        }
        return false;
    }

    @Override
    public boolean updatePaperTrackRecord(PaperTrackRecord paperTrackRecord) {
        int count = testPaperMapper.updatePaperTrackRecord(paperTrackRecord);
        if (count > 0) {
            return true;
        }
        return false;
    }

    @Override
    public boolean updatePaperQuestionSort(Map paramMap) {
        int count = testPaperMapper.batchUpdatePaperQuestionSort(paramMap);
        if (count > 0) {
            return true;
        }
        return false;
    }

    @Override
    public boolean checkPaperHasDone(Integer paperId) {
        int count = testPaperMapper.selectPaperHasDone(paperId);
        if (count > 0) {
            return true;
        }
        return false;
    }

    /**
     * 试卷启用禁用
     *
     * @param paperId 试卷ID
     * @return 结果
     */
    @Override
    public boolean changePaperAvailableState(Integer paperId, Integer state) {
        int count = testPaperMapper.changePaperAvailableState(paperId,state);
        if (count > 0) {
            return true;
        }
        return false;
    }
}
